home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue52 / HTML / Code / AppServer / svrSubmitHandler.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-10-26  |  6.0 KB  |  204 lines

  1. unit svrSubmitHandler;
  2.  
  3. interface
  4.  
  5. uses
  6.   Classes, DBTables, SysUtils, dpoBase, mleCommon, usXMLDoc;
  7.  
  8. resourcestring
  9.   SSubmitInvalidClassType = '%s is not a valid business object class';
  10.   SSubmitNoBindingInfo = 'No binding information found for instance "%s"';
  11.   SSubmitUnsupportedDatatype = 'Cannot assign value to "%s.%s"; unsupported datatype (%s)';
  12.  
  13. type
  14.   ESubmitException = class(Exception);
  15.   ESubmitInvalidClassType = class(ESubmitException);
  16.   ESubmitNoBindingInfo = class(ESubmitException);
  17.   ESubmitUnsupportedDatatype = class(ESubmitException);
  18.  
  19. type
  20.   TProcessingInstruction = (piUndefined, piInsert, piUpdate, piDelete);
  21.  
  22.   TSubmitHandler = class(TComponent)
  23.   protected
  24.     Variables: TStrings;
  25.     Database: TDatabase;
  26.     Parser: TusXMLParser;
  27.     DataBindings: TusXMLDocument;
  28.     InstanceData: TusXMLElement;
  29.     InstanceName: string;
  30.     Instance: TDataObject;
  31.     procedure CreateInstance(aInstanceName: string);
  32.     function GetDataObjectClass(aClassName: string): TDataObjectClass;
  33.     procedure SetInstanceProperties;
  34.   public
  35.     constructor Create(aOwner: TComponent; aPacket: TInfoPacket); reintroduce; virtual;
  36.     destructor Destroy; override;
  37.     function GetContent: string; virtual;
  38.   end;
  39.  
  40. implementation
  41.  
  42. uses
  43.   svrPageHandler;
  44.  
  45. { TSubmitHandler }
  46.  
  47. constructor TSubmitHandler.Create(aOwner: TComponent; aPacket: TInfoPacket);
  48. begin
  49.   inherited Create(aOwner);
  50.   Database := aPacket.Database;
  51.   Variables := aPacket.Variables;
  52.   Parser := TusXMLParser.Create;
  53. end;
  54.  
  55. procedure TSubmitHandler.CreateInstance(aInstanceName: string);
  56. var
  57.   I: Integer;
  58.   InstanceClass: TDataObjectClass;
  59. begin
  60.   InstanceName := aInstanceName;
  61.   InstanceClass := nil;
  62.  
  63.   { Locate the data binding information for the instance }
  64.   if not Assigned(DataBindings) then
  65.     raise ESubmitNoBindingInfo.CreateFmt(SSubmitNoBindingInfo, [InstanceName]);
  66.  
  67.   { DataBindings points to the <DATABINDINGS> element }
  68.   for I := 0 to DataBindings.Root.Subtags.Count - 1 do
  69.   begin
  70.     { InstanceData points to an <INSTANCE> element }
  71.     InstanceData := DataBindings.Root.Subtags[I];
  72.     with InstanceData do
  73.     begin
  74.       { <INSTANCE class="xxx" oid="xxx" name="xxx"> }
  75.       if CompareText(Attributes.Value('name'), InstanceName) = 0 then
  76.       begin
  77.         { transform class name into class type }
  78.         InstanceClass := GetDataObjectClass(Attributes.Value('class'));
  79.         if not Assigned(InstanceClass) then
  80.           raise ESubmitInvalidClassType.CreateFmt(SSubmitInvalidClassType, [Attributes.Value('class')]);
  81.  
  82.         { Instantiate the data object }
  83.         Instance := InstanceClass.Create(Database);
  84.  
  85.         { Load the data object with data }
  86.         Instance.GetByOID(Attributes.Value('oid'));
  87.  
  88.         Break;
  89.       end;
  90.     end;
  91.   end;
  92.  
  93.   if not Assigned(InstanceClass) then
  94.     raise ESubmitNoBindingInfo.CreateFmt(SSubmitNoBindingInfo, [InstanceName]);
  95. end;
  96.  
  97. destructor TSubmitHandler.Destroy;
  98. begin
  99.   Parser.Free;
  100.   inherited;
  101. end;
  102.  
  103. function TSubmitHandler.GetContent: string;
  104. var
  105.   I: Integer;
  106.   ProcessingInstruction: TProcessingInstruction;
  107. begin
  108.   Result := '';
  109.  
  110.   Parser.LoadXML(Variables.Values['SMLDataBindings']);
  111.   DataBindings := Parser.Document;
  112.  
  113.   { Find all the processing instructions that were passed in as URL parameters. }
  114.   with Variables do
  115.   begin
  116.     for I := 0 to Count - 1 do
  117.     begin
  118.       ProcessingInstruction := piUndefined;
  119.       if (CompareText(Names[I], 'pi:update') = 0) then
  120.         ProcessingInstruction := piUpdate;
  121.       if (CompareText(Names[I], 'pi:insert') = 0) then
  122.         ProcessingInstruction := piInsert;
  123.       if (CompareText(Names[I], 'pi:delete') = 0) then
  124.         ProcessingInstruction := piDelete;
  125.  
  126.       { Processing only continues when we've found a processing instruction }
  127.       if ProcessingInstruction = piUndefined then
  128.         Continue;
  129.  
  130.       CreateInstance(Values[Names[I]]);
  131.       try
  132.         case ProcessingInstruction of
  133.           piUpdate,
  134.           piInsert: SetInstanceProperties;
  135.           piDelete: Instance.Delete;
  136.         end;
  137.       finally
  138.       end;
  139.     end;
  140.   end;
  141. end;
  142.  
  143. function TSubmitHandler.GetDataObjectClass(aClassName: string): TDataObjectClass;
  144. var
  145.   AClass: TClass;
  146. begin
  147.   Result := nil;
  148.   AClass := GetClass(aClassName);
  149.   if Assigned(AClass) then
  150.     if AClass.InheritsFrom(TDataObject) then
  151.       Result := TDataObjectClass(AClass)
  152. end;
  153.  
  154. procedure TSubmitHandler.SetInstanceProperties;
  155. var
  156.   I, J: Integer;
  157.   BindingData: TusXMLElement;
  158.   ControlName: string;
  159.   PropertyName: string;
  160.   NewValue: string;
  161. begin
  162.   { For each property specified in the binding information, find its current
  163.     value in the variable list and set the applicable data object property. }
  164.   BindingData := nil;  
  165.   with InstanceData.Subtags do
  166.   begin
  167.     { Find the <BINDINGS> tag }
  168.     for I := 0 to Count - 1 do
  169.       if CompareText(Items[I].TagName, 'bindings') = 0 then
  170.       begin
  171.         BindingData := Items[I];
  172.         Break;
  173.       end;
  174.     if not Assigned(BindingData) then
  175.       raise ESubmitNoBindingInfo.CreateFmt(SSubmitNoBindingInfo, [InstanceName]);
  176.  
  177.     { Loop though all the property assignments for this instance }
  178.     { Each subtag of <BINDINGS> is a <BINDING> tag, so look for subtags
  179.       under <BINDING> }
  180.     for I := 0 to BindingData.Subtags.Count - 1 do
  181.     begin  { a <BINDING> tag }
  182.       with BindingData.Subtags[I].Subtags do
  183.         for J := 0 to Count - 1 do
  184.         begin  { a subtag under <BINDING> }
  185.           if CompareText(Items[J].TagName, 'property') = 0 then
  186.             PropertyName := Items[J].Data;
  187.           if CompareText(Items[J].TagName, 'control') = 0 then
  188.             ControlName := Items[J].Data;
  189.         end;
  190.  
  191.       if Variables.IndexOfName(ControlName) <> -1 then
  192.       begin
  193.         NewValue := Variables.Values[ControlName];
  194.         Instance.EditMode;
  195.         Instance.PropertyByName(PropertyName).AsVariant := NewValue;
  196.       end;
  197.     end;
  198.     if Instance.Modified then
  199.       Instance.Save;
  200.   end;
  201. end;
  202.  
  203. end.
  204.